pragma Singleton

import QtQuick 2.0
import RabbitMqClient 1.0
import "."

Item {
    id: id_root
    QtObject {
        id: id_internal
        property int subscribeId: 0
        property var rabbitmqClients: ({})
        property string uri: "amqp://icsmq:icsmq@10.68.41.47:5672/"
    }

    Timer {
        id: timer
    }

    function setTimeout(cb, delayTime) {
        timer.interval = delayTime
        timer.repeat = false
        timer.triggered.connect(cb)
        timer.start()
    }

    function request(servicename, msg, timeout = 5000) {
        var promise = new Promise(function (resolve, reject) {
            var reqid = publish(servicename, msg, function (msg) {
                var jObj = JSON.parse(msg)
                if (jObj.hasOwnProperty("rc") && (jObj.rc === 200
                                                  || jObj.rc === 0)) {
                    resolve(msg)
                } else {
                    reject(msg)
                }
            }, timeout)
            setTimeout(function () {
                if (!_isResolved(servicename, reqid)) {
                    reject("timeout")
                    console.warn("request timeout,request to servicename:"
                                 + servicename + " msg:" + msg)
                }
            }, timeout)
        })
        return promise
    }

    function publish(servicename, msg, callback, timeout = 5000) {
        var reqId = 0
        if (id_internal.rabbitmqClients.hasOwnProperty(servicename)) {
            reqId = id_internal.rabbitmqClients[servicename].request(msg,
                                                                     timeout)
            id_internal.rabbitmqClients[servicename].req_callbacks[reqId] = callback
        } else {
            console.warn("publish failed, due to unknown service name:",
                         servicename)
            return 0
        }
        return reqId
    }
    function subscribe(servicename, callback) {
        var sid = id_internal.subscribeId++
        if (id_internal.rabbitmqClients.hasOwnProperty(servicename)) {
            id_internal.rabbitmqClients[servicename].sub_callbacks[sid] = callback
        } else {
            console.warn("can not find the subscribe servicename:", servicename)
            return 0
        }
        return sid
    }

    function unsubscribe(sid) {
        for (var key in id_internal.rabbitmqClients) {
            if (id_internal.rabbitmqClients[key].sub_callbacks.hasOwnProperty(
                        sid)) {
                console.debug("unsubscribe procedure subscribe id:", sid)
                delete id_internal.rabbitmqClients[key].sub_callbacks[sid]
            }
        }
    }

    function _isResolved(servicename, reqid) {
        if (id_internal.rabbitmqClients.hasOwnProperty(servicename)) {
            return !id_internal.rabbitmqClients[servicename].req_callbacks.hasOwnProperty(
                        reqid)
        } else {
            console.warn("isResolved unknown service name:", servicename)
            return false
        }
    }

    function _handlerSubscribeMsg(client, msg) {
        try {
            for (var key in client.sub_callbacks) {
                client.sub_callbacks[key](msg)
            }
        } catch (e) {
            console.warn(client.servicename + " onSubscribedMsg exception:" + e)
        }
    }
    function _handleResponse(client, reqId, msg) {
        try {
            if (client.req_callbacks.hasOwnProperty(reqId)) {
                client.req_callbacks[reqId](msg)
                delete client.req_callbacks[reqId]
            }
        } catch (e) {
            console.warn(client.servicename + " onResponseMsg exception:" + e)
        }
    }

    function _handlerResponseTimeout(client, reqId, msg) {
        try {
            if (client.req_callbacks.hasOwnProperty(reqId)) {
                delete client.req_callbacks[reqId]
            }
        } catch (e) {
            console.warn(client.servicename + " onResponseTimeout exception:" + e)
        }
    }

    RabbitMqClient {
        id: rmq_storage_client
        servicename: Utils._SERVICE_NAME_STORAGE
        property var req_callbacks: ({})
        property var sub_callbacks: ({})
        onSubscribedMsg: function (msg) {
            id_root._handlerSubscribeMsg(rmq_storage_client, msg)
        }
        onResponseMsg: function (reqId, msg) {
            id_root._handleResponse(rmq_storage_client, reqId, msg)
        }
        onResponseTimeout: function (reqId, msg) {
            id_root._handlerResponseTimeout(rmq_storage_client, reqId, msg)
        }
        Component.onCompleted: {
            id_internal.rabbitmqClients[servicename] = rmq_storage_client
            rmq_storage_client.start(id_internal.uri)
        }
    }
    RabbitMqClient {
        id: rmq_procedure_client
        servicename: Utils._SERVICE_NAME_PROCEDURE
        property var req_callbacks: ({})
        property var sub_callbacks: ({})
        onSubscribedMsg: function (msg) {
            id_root._handlerSubscribeMsg(rmq_procedure_client, msg)
        }
        onResponseMsg: function (reqId, msg) {
            id_root._handleResponse(rmq_procedure_client, reqId, msg)
        }
        onResponseTimeout: function (reqId, msg) {
            id_root._handlerResponseTimeout(rmq_procedure_client, reqId, msg)
        }
        Component.onCompleted: {
            id_internal.rabbitmqClients[servicename] = rmq_procedure_client
            rmq_procedure_client.start(id_internal.uri)
        }
    }
}
